package org.yufan.user.service.impl;

import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.yufan.common.exception.CustomerException;
import org.yufan.common.result.ResultEnum;
import org.yufan.common.utils.JwtUtil;
import org.yufan.user.bean.User;
import org.yufan.user.repository.UserRepository;
import org.yufan.user.service.UserService;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
@Slf4j
public class UserServiceImpl implements UserService {


    private static final String USER_TOKEN = "user_token:";

    private static final String USER_LOGIN = "login";

    public static final String USER_LOGIN_SMS = "user_login_sms:";

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RedisTemplate redisTemplate;

//    @Autowired
//    private RabbitTemplate rabbitTemplate;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public void register(User user) throws CustomerException {
        //1.参数校验
        checkUser(user);
        //2.判断信息是否已经使用
        judgeUser(user);
        user.setCreated(new Date());
        user.setUpdated(user.getCreated());
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userRepository.save(user);
    }

    @Override
    public String login(String username, String password) throws CustomerException {

        if (StringUtils.isEmpty(username)) {
            log.debug("用户名不能为空!");
            throw new CustomerException(ResultEnum.USERNAME_NOT_EMPTY);
        }
        if (StringUtils.isEmpty(password)) {
            log.debug("密码不能为空!");
            throw new CustomerException(ResultEnum.PASSWORD_NOT_EMPTY);
        }
        //获取用户信息
        User user = userRepository.findUserByUsername(username);
        if (user == null) {
            log.info("用户不存在,{}", username);
            throw new CustomerException(ResultEnum.LOGIN_FAIL);
        }


        //比较密码
        if (!passwordEncoder.matches(password, user.getPassword())) {
            log.info("密码错误,用户名为{}", username);
            throw new CustomerException(ResultEnum.FAIL);
        }


        String token = dealLogin(user);
        return token;
    }



    private String dealLogin(User user) {
        Map<String, Object> map = new HashMap<>();
        map.put("username", user.getUsername());
        map.put("phone", user.getPhone());
        map.put("email", user.getEmail());
        map.put("id",user.getId());
        map.put("created",user.getCreated());
        map.put("updated",user.getUpdated());
        String token = jwtUtil.createJWT(user.getId() + "", user.getUsername(), map);

        //生成jwt令牌
        return token;
    }

    @Override
    public User queryUserByToken(String token) throws CustomerException {
        if (StringUtils.isEmpty(token)) {
            log.debug("token为空");
            throw new CustomerException(ResultEnum.TOKEN_NOT_EMPTY);
        }
       return  jwtUtil.parseUser(token);
    }




    @Override
    public String loginByPhone(String phone, String code) throws CustomerException {
        if (StringUtils.isEmpty(phone)) {
            throw new CustomerException(ResultEnum.PHONE_NOT_EMPTY);
        }
        if (StringUtils.isEmpty(code)) {
            throw new CustomerException(ResultEnum.CHECK_CODE_NOT_EMPTY);
        }
        //判断用户是否已经注册
        User user = userRepository.findUserByPhone(phone);
        if (user == null) {
            throw new CustomerException(ResultEnum.PHONE_NOT_REGISTER);
        }

        String serverCode = (String) redisTemplate.boundValueOps(USER_LOGIN_SMS + phone).get();

        if (StringUtils.isEmpty(serverCode)) {
            throw new CustomerException(ResultEnum.CHECK_CODE_EXPIRY);
        }
        if (!code.equals(serverCode)) {
            throw new CustomerException(ResultEnum.CHECK_CODE_ERROR);
        }
        log.info("处理登录:{}，删除验证码{}", phone, serverCode);
        redisTemplate.delete(USER_LOGIN_SMS + phone);
        return dealLogin(user);
    }


    /**
     * 判断用户信息是否使用
     *
     * @param user
     */
    private void judgeUser(User user) throws CustomerException {

        if (userRepository.findUserByUsername(user.getUsername()) != null) {
            log.info("用户名已经使用:{}", user.getUsername());
            throw new CustomerException(ResultEnum.USERNAME_EXIST);
        }
        if (userRepository.findUserByEmail(user.getEmail()) != null) {
            log.info("邮箱已经使用:{}", user.getEmail());
            throw new CustomerException(ResultEnum.EMAIL_EXIST);
        }
        if (userRepository.findUserByPhone(user.getPhone()) != null) {
            log.info("电话已经使用:{}", user.getPhone());
            throw new CustomerException(ResultEnum.PHONE_EXIST);
        }
    }

    /**
     * 参数校验
     *
     * @param user
     * @throws CustomerException
     */
    private void checkUser(User user) throws CustomerException {
        if (user == null) {
            log.error("用户信息为空!");
            throw new CustomerException(ResultEnum.USER_NOT_EMPTY);
        }
        if (StringUtils.isEmpty(user.getUsername())) {
            log.error("用户名为空!");
            throw new CustomerException(ResultEnum.USERNAME_NOT_EMPTY);
        }
        if (StringUtils.isEmpty(user.getPassword())) {
            log.error("密码为空!");
            throw new CustomerException(ResultEnum.PASSWORD_NOT_EMPTY);
        }
        if (StringUtils.isEmpty(user.getEmail())) {
            log.error("邮箱为空!");
            throw new CustomerException(ResultEnum.EMAIL_NOT_EMPTY);
        }
    }


    @Override
    public void sendLoginSms(String phone) throws CustomerException {
        if (StringUtils.isEmpty(phone)) {
            throw new CustomerException(ResultEnum.PHONE_NOT_EMPTY);
        }
        //判断用户是否已经注册
        if (userRepository.findUserByPhone(phone) == null) {
            throw new CustomerException(ResultEnum.PHONE_NOT_REGISTER);
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb.append(new Random().nextInt(10));
        }
        String code = sb.toString();
        log.info("用户的验证码为:{}", code);
        redisTemplate.boundValueOps(USER_LOGIN_SMS + phone).set(code);
        redisTemplate.boundValueOps(USER_LOGIN_SMS + phone).expire(5, TimeUnit.MINUTES);

        try {
            // 发送短信
            Map<String, String> msg = new HashMap<>();
            msg.put("phone", phone);
            msg.put("code", code);
//            this.rabbitTemplate.convertAndSend("yufan.sms.exchange", "sms.verify.code", msg);
            // 将code存入redis
        } catch (Exception e) {
            log.error("发送短信失败。phone：{}， code：{}", phone, code);
            throw new CustomerException(ResultEnum.FAIL);
        }

    }


}
